package org.example.java_gobang.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.java_gobang.game.MatchRequest;
import org.example.java_gobang.game.MatchResponse;
import org.example.java_gobang.game.Matcher;
import org.example.java_gobang.game.OnlineUserManager;
import org.example.java_gobang.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Component
//通过这个类 来处理匹配功能中的websocket 请求
public class MatchAPI extends TextWebSocketHandler {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private Matcher matcher;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //玩家上线  ,加入到 OnlineUserManager 中

        //1.先获取当前用户的身份信息 也就是谁在游戏大厅中建立的连接
        //此次的代码,之所以能够 getAttributes,全靠注册Websocket的时候
        //加上的 .addInterceptors(new HttpSessionHandshakeInterceptor());
        //这个逻辑就是把 HttpSession中的 Attribute 都给拿到 WebSocketSession中了
        //httpSession.setAttribute("user",user);  这个在登录中也有设计这个逻辑 在HttpSession
        //中存了User对象

        //此时user也可能为空对象  ,就是也可能之前用户没有通过HTTP登录  ,而是直接
        //通过/game_hall.html这个url来访问游戏大厅页面  此时就会出现user为空的情况
        try{
            User user = (User) session.getAttributes().get("user");

            //2.先要判定当前用户是否已经登录过了  (是否是在线状态),如果是已经在线,就不能再进行接下来的逻辑
           // WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if (onlineUserManager.getFromGameHall(user.getUserId()) != null
                       || onlineUserManager.getFromGameRoom(user.getUserId()) != null) {
                //当前用户已经登录好了
                //告诉这个情况给  客户端  你已经重复登录了  禁止多开
                MatchResponse response = new MatchResponse();
                response.setOk(true);
                response.setReason("当前禁止多开");
                response.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                //此处直接关闭有些激进  还是返回一个特殊的 message,供客户端来判定  由客户端进行处理
               // session.close();
                return;
            }

            //3.拿到身份信息后,  就可以把玩家设置成在线状态了
            onlineUserManager.enterGameHall(user.getUserId(),session);
            System.out.println("玩家 " + user.getUsername() + "进入游戏大厅!");
        }catch (NullPointerException e) {
            System.out.println("[MatchAPI.afterConnectionEstablished] 当前用户未登录!");
           // e.printStackTrace();
            //出现空指针异常,说明当前用户没有登录  身份信息为空
            //把当前用户尚未登录的这个信息返回去
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("你尚未登录! 不能进行匹配!");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response))); //把JSON对象转化为字符串
        }

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //实现处理开始匹配请求和处理停止匹配请求
        User user = (User) session.getAttributes().get("user");
        //获取到客户端给服务器发送的数据
        String payload = message.getPayload();
        //当前这个数据载荷是一个JSON格式的字符串,  需要把他转化为 Java对象 MatchRequest
        MatchRequest request = objectMapper.readValue(payload,MatchRequest.class);
        //要一个响应对象  把 数据返回给客户端
        MatchResponse response = new MatchResponse();
        if (request.getMessage().equals("startMatch")) {
            //进入 匹配队列
            matcher.add(user);

            //把玩家信息 放入匹配队列之后,就可以返回一个响应给客户端了
            response.setOk(true);
            response.setMessage("startMatch");

        }else if (request.getMessage().equals("stopMatch")) {
            //退出匹配队列

            matcher.remove(user);
            //移除之后,就可以返回一个响应给客户端了
            response.setOk(true);
            response.setMessage("stopMatch");
        }else {
            //非法的情况
            response.setOk(false);
            response.setMessage("非法匹配请求");
        }
        String jsonString = objectMapper.writeValueAsString(response);
        session.sendMessage(new TextMessage(jsonString));
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        //玩家下线  ,从 OnlineUserManager 中删除
        try {
            User user = (User) session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if (tmpSession == session) {
                //这里判断的目的也就是为了 防止多开把之前的用户Session删掉  要保证登录的Session和之前的一样才能删
                onlineUserManager.exitGameHall(user.getUserId());
            }
            //如果玩家正在匹配中  如果websocket 连接断开了 就应该移除匹配队列
            matcher.remove(user);
        }catch (NullPointerException e) {
            System.out.println("[MatchAPI.handleTransportError]当前用户未登录!");

         //   e.printStackTrace();
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("你尚未登录! 不能进行匹配!");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response))); //把JSON对象转化为字符串
        }

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        //玩家下线  ,从 OnlineUserManager 中删除
        try {
            User user = (User) session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if (tmpSession == session) {
                onlineUserManager.exitGameHall(user.getUserId());
            }
            //如果玩家正在匹配中  如果websocket 连接断开了 就应该移除匹配队列
            matcher.remove(user);
        }catch (NullPointerException e) {
            System.out.println("[MatchAPI.afterConnectionClosed]当前用户未登录!");

           // e.printStackTrace();

            //不应该在连接关闭之后,还尝试发消息给客户端
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("你尚未登录! 不能进行匹配!");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response))); //把JSON对象转化为字符串
        }

    }
}
